package com.ybe.handler.exchange;

import com.sun.net.httpserver.HttpExchange;
import com.ybe.exception.BadRequest;
import com.ybe.exception.Unauthorized;
import com.ybe.handler.exchange.annotation.HttpExchangeAnnotation;
import com.ybe.session.Session;
import com.ybe.session.SessionHolder;
import com.ybe.stake.StakeHolder;
import com.ybe.util.CommonUtil;
import com.ybe.util.HttpExchangeUtil;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@HttpExchangeAnnotation
public class StakeHandler implements HttpExchangeHandler {

    private static final Pattern POST_STAKE_PATH = Pattern.compile("^/(\\d+)/stake/?$");

    @Override
    public void handler(HttpExchange exchange) {
        String path = exchange.getRequestURI().getPath();
        Matcher m = POST_STAKE_PATH.matcher(path);
        if (!m.matches()) {
            return;
        }

        try {
            int betOfferId = CommonUtil.parseInt(m.group(1));
            long now = System.currentTimeMillis();
            String sessionKey = CommonUtil.getQueryParam(exchange.getRequestURI().getRawQuery(), "sessionkey");
            if (sessionKey == null || sessionKey.isEmpty()) {
                throw new Unauthorized();
            }

            Session session = SessionHolder.getSessionByKey(sessionKey);
            if (session == null || session.isExpired(now)) {
                throw new Unauthorized();
            }

            int customerId = session.getCustomerId();
            String body = CommonUtil.readBody(exchange);
            int stake = CommonUtil.parseInt(body.trim());
            if (stake < 0) {
                throw new BadRequest("stake must be non-negative");
            }

            StakeHolder.getStakesByOffer()
                    .computeIfAbsent(betOfferId, k -> new ConcurrentHashMap<>())
                    .compute(customerId, (cid, oldVal) -> (oldVal == null) ? stake : Math.max(oldVal, stake));
            HttpExchangeUtil.sendEmpty(exchange, 204);


        } catch (NumberFormatException e) {
            throw new BadRequest("stake is not int type");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean isMatch(HttpExchange exchange) {
        String path = exchange.getRequestURI().getPath();
        final String method = exchange.getRequestMethod();
        return POST_STAKE_PATH.matcher(path).matches() && "POST".equalsIgnoreCase(method);
    }
}
